/*
 *
 *  * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 *
 *
 */

package com.iwindplus.base.monitor.support;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.iwindplus.base.monitor.domain.property.MonitorProperty;
import io.micrometer.observation.ObservationRegistry;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer;
import org.springframework.http.client.observation.ClientRequestObservationContext;
import org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.util.AntPathMatcher;

/**
 * 自定义 ObservationRegistry 的定制器，用于根据配置忽略指定路径的请求观测（即不记录这些路径的指标）.
 *
 * @author zengdegui
 * @since 2025/09/24 20:39
 */
@Slf4j
public class CustomObservationRegistryCustomizer {

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    private static final List<String> DEFAULT_IGNORED_APIS = List.of(
        "/actuator/prometheus/**"
    );

    /**
     * 创建一个 ObservationRegistryCustomizer 对象，用于根据配置忽略指定路径的请求观测（即不记录这些路径的指标）。
     *
     * @param property 配置属性
     * @return ObservationRegistryCustomizer 对象
     */
    public ObservationRegistryCustomizer<ObservationRegistry> customizer(MonitorProperty property) {
        // 合并默认 + 配置
        Set<String> patterns = new HashSet<>(DEFAULT_IGNORED_APIS);
        if (CollUtil.isNotEmpty(property.getIgnoredApi())) {
            patterns.addAll(property.getIgnoredApi());
        }
        log.info("[Observation] 忽略指标 URI 模式：{}", patterns);

        return registry -> registry.observationConfig().observationPredicate((name, context) -> {
            // 1. 服务器端（WebFlux / MVC）
            if (context instanceof ServerRequestObservationContext src) {
                String path = src.getCarrier().getRequestURI();
                if (CharSequenceUtil.isBlank(path)) {
                    return true;
                }
                return patterns.stream().noneMatch(p -> PATH_MATCHER.match(p, path));
            }

            // 2. 客户端（WebClient、Gateway 转发）
            if (context instanceof ClientRequestObservationContext crc) {
                URI uri = crc.getCarrier().getURI();
                if (uri == null) {
                    return true;
                }
                String path = uri.getPath();
                return patterns.stream().noneMatch(p -> PATH_MATCHER.match(p, path));
            }

            // 3. 其它观测，默认放过
            return true;
        });
    }

}
